﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NLog;
using Farigola.Engine.Factories;
using Farigola.Engine.Reposit;

namespace Farigola.Engine
{

    /// <summary>
    /// The engine, core of the farigola application.
    /// A concrete repository is not mandatory indev or tests,
    /// but its better to have one in prod.
    /// 
    /// Configure the logger NLog: http://nlog-project.org/wiki/Tutorial#Log_levels
    /// 
    /// </summary>
    public class Engine : IDisposable
    {
        // log, how?
        // externalize the log, by an event dispatcher?
        // or use the std log. 
        private static Logger logger = LogManager.GetCurrentClassLogger();

        /// <summary>
        /// The factory to build all object: workspace, project, and all
        /// domain objects of the application.
        /// </summary>
        private Factory _factory;

        /// <summary>
        /// Manager of errors/exceptions occurs in the engine.
        /// save errors of the last action (last called method).
        /// </summary>
        //private ErrorMgr _errorMgr;

        /// <summary>
        /// Manager of tasks activity in the application (trace)
        /// Manage alos errors occurs in the engine.
        /// </summary>
        private AppActivityMgr _appActivityMgr;

        /// <summary>
        /// repository, to persist data (by DI) of the project.
        /// </summary>
        private IEngineReposit _engineReposit;

        /// <summary>
        /// the unique workspace of the engine core, run in memory, 
        /// its just a container of projects, and specialy of the active project. 
        /// </summary>
        private Workspace _workspace;

        /**
         * a flag to know if the initialization of th core is done or not.
         */
        private bool _initDone = false;

        public bool IsInitDone
        {
            get { return _initDone; }
        }

        //private static ErrorMgr _errorMgr;

        //public static ErrorMgr GetErrorMgr()
        //{
        //    if (_errorMgr == null)
        //        _errorMgr = new ErrorMgr();
        //    return _errorMgr;
        //}

        //---------------------------------------------------------------------
        /// <summary>
        ///  Constructor.
        /// Set (inject) the concrete repository to persist all data.
        /// </summary>
        public Engine()
        {
            logger.Info("----------");
            logger.Info("start the Farigola engine.");

            _engineReposit = null;
        }

        //---------------------------------------------------------------------
        /// <summary>
        ///  Constructor.
        /// Set (inject) the concrete repository to persist all data.
        /// </summary>
        public Engine(IEngineReposit engineReposit)
        {
            logger.Info("----------");
            logger.Info("start the Farigola engine.");

            _engineReposit = engineReposit;
        }

        //---------------------------------------------------------------------
        /// <summary>
        /// Check the internal content of the object, after the init.
        /// 
        /// workspace internal content, after init.
        ///
        ///  its a basic check, if an error occurs, return false.
        ///
        /// </summary>
        /// <returns></returns>
        public bool CheckInternal()
        {
            if (_factory == null)
                return false;

            if (_workspace == null)
                return false;

            if (_appActivityMgr == null)
                return false;

            // check engine repository?
            // todo:

            if (!_initDone)
                return false;

            // all is ok
            return true;
        }

        //---------------------------------------------------------------------
        public Workspace GetWorkspace()
        {
            return _workspace;
        }

        //---------------------------------------------------------------------
        /// <summary>
        /// Init the engine core.
        /// The concrete repository must be present.
        /// </summary>
        /// <returns></returns>
        public bool Init()
        {
            if (_initDone)
                return false;

            // get the factory
            //_factory = Factory.GetFactory();
            _factory = new Factory();

            _appActivityMgr = _factory.CreateAppActivityMgr();

            // create the workspace
            _workspace = _factory.CreateWorkspace();


            // if a concrete repository is present, propagate it
            if (_engineReposit != null)
            {
                _engineReposit.SetAppActivityMgr(_appActivityMgr);
                //return false;
                _workspace.SetProjectReposit(_engineReposit.GetProjectReposit());
            }

            // init the workspace
            _workspace.Init();

            // ok, the init of the core is done
            _initDone = true;
            return true;
        }

        //---------------------------------------------------------------------
        /// <summary>
        /// Return the default project present in the core.
        /// managed by the workspace.
        /// </summary>
        /// <returns></returns>
        public Project GetActiveProject()
        {
            if (_workspace == null)
                return null;

            return _workspace.GetActiveProject();
        }

        //---------------------------------------------------------------------
        /// <summary>
        /// Create a project in the current workspace,
        /// becomes the active project.
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        //public Project CreateActiveProject(String name)
        //{
        //    // no workspace present, need to init the engine
        //    if (_workspace == null)
        //        return null;
        //    return _workspace.CreateActiveProject(name);
        //}

        //---------------------------------------------------------------------
        /// <summary>
        /// save the active project.
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        //public bool SaveActiveProject(string fileName)
        //{
        //    // no workspace present, need to init the engine
        //    if (_workspace == null)
        //        return false;
        //    return _workspace.SaveActiveProject(fileName);
        //}


        //---------------------------------------------------------------------
        /// <summary>
        /// close (remove from the workspace) the active project.
        /// </summary>
        /// <returns></returns>
        //public bool CloseActiveProject()
        //{
        //    // no workspace present, need to init the engine
        //    if (_workspace == null)
        //        return false;
        //    return _workspace.CloseActiveProject();
        //}

        //---------------------------------------------------------------------
        /// <summary>
        /// load a saved project, becomes the active project.
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        //public Project LoadActiveProject(string fileName)
        //{
        //    // no workspace present, need to init the engine
        //    if (_workspace == null)
        //        return null;
        //    return _workspace.LoadActiveProject(fileName);
        //}

        //=====================================================================
        #region IDisposable Members

        //---------------------------------------------------------------------
        public void Dispose()
        {
            // TODO: clean all objects.
            // manage the persistence mechanims
            //throw new NotImplementedException();
        }

        #endregion
    }
}
